//
//  SystemFileManager.m
//  YuanXinKit
//
//  Created by 晏德智 on 2016/11/4.
//  Copyright © 2016年 晏德智. All rights reserved.
//

#import "SystemFileManager.h"

NSString *const STORAGE_BACKED_UP = @"BACKED_UP";
NSString *const STORAGE_IMPORTANT = @"IMPORTANT";
NSString *const STORAGE_AUXILIARY = @"AUXILIARY";
NSString *const STORAGE_TEMPORARY = @"TEMPORARY";

@implementation SystemFileManager

+ (NSURL*)baseDirForStorage:(NSString*)storage {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([storage isEqual:STORAGE_BACKED_UP]) {
        return [fileManager URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
    } else if ([storage isEqual:STORAGE_IMPORTANT]) {
        NSURL *cachesDir = [fileManager URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
        return [cachesDir URLByAppendingPathComponent:@"Important"];
    } else if ([storage isEqual:STORAGE_AUXILIARY]) {
        NSURL *cachesDir = [fileManager URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
        return [cachesDir URLByAppendingPathComponent:@"Auxiliary"];
    } else if ([storage isEqual:STORAGE_TEMPORARY]) {
        return [NSURL fileURLWithPath:NSTemporaryDirectory()];
    } else {
        [NSException raise:@"InvalidArgument" format:@"%@", [NSString stringWithFormat:@"Storage type not recognized: %@", storage]];
        return nil;
    }
}

+ (void)createDirectoriesIfNeeded:(NSURL*)path {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *directory = [[path URLByDeletingLastPathComponent] path];
    [fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:nil];
    
}

+ (void)writeToFile:(NSString*)relativePath content:(NSString*)content inStorage:(NSString*)storage {
    NSURL *baseDir = [SystemFileManager baseDirForStorage:storage];
    NSURL *fullPath = [baseDir URLByAppendingPathComponent:relativePath];
    [SystemFileManager createDirectoriesIfNeeded:fullPath];
    
    [content writeToFile:[fullPath path] atomically:YES encoding:NSUTF8StringEncoding error:nil];
    if ([storage isEqual:STORAGE_IMPORTANT]) {
        [SystemFileManager addSkipBackupAttributeToItemAtPath:[fullPath path]];
    }
}

+ (NSString*)readFile:(NSString*)relativePath inStorage:(NSString*)storage error:(NSError**)error {
    NSURL *baseDir = [SystemFileManager baseDirForStorage:storage];
    NSURL *fullPath = [baseDir URLByAppendingPathComponent:relativePath];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL fileExists = [fileManager fileExistsAtPath:[fullPath path]];
    if (!fileExists) {
        NSString* errorMessage = [NSString stringWithFormat:@"File '%@' does not exist in storage: %@", relativePath, storage];
        NSDictionary *errorDetail = @{NSLocalizedDescriptionKey: errorMessage};
        *error = [NSError errorWithDomain:@"FSComponent" code:1 userInfo:errorDetail];
        return nil;
    }
    return [NSString stringWithContentsOfFile:[fullPath path] encoding:NSUTF8StringEncoding error:nil];
}

+ (BOOL)fileExists:(NSString*)relativePath inStorage:(NSString*)storage {
    NSURL *baseDir = [SystemFileManager baseDirForStorage:storage];
    NSURL *fullPath = [baseDir URLByAppendingPathComponent:relativePath];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isDirectory;
    BOOL exists = [fileManager fileExistsAtPath:[fullPath path] isDirectory:&isDirectory];
    return exists & !isDirectory;
}

+ (BOOL)directoryExists:(NSString*)relativePath inStorage:(NSString*)storage {
    NSURL *baseDir = [SystemFileManager baseDirForStorage:storage];
    NSURL *fullPath = [baseDir URLByAppendingPathComponent:relativePath];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isDirectory;
    BOOL exists = [fileManager fileExistsAtPath:[fullPath path] isDirectory:&isDirectory];
    return exists & isDirectory;
}

+ (BOOL)deleteFileOrDirectory:(NSString*)relativePath inStorage:(NSString*)storage {
    NSURL *baseDir = [SystemFileManager baseDirForStorage:storage];
    NSURL *fullPath = [baseDir URLByAppendingPathComponent:relativePath];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL fileExists = [fileManager fileExistsAtPath:[fullPath path]];
    if (!fileExists) {
        return NO;
    }
    [fileManager removeItemAtPath:[fullPath path] error:nil];
    return YES;
}

+ (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString
{
    NSURL* URL= [NSURL fileURLWithPath: filePathString];
    assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
    
    NSError *error = nil;
    BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
                                  forKey: NSURLIsExcludedFromBackupKey error: &error];
    if(!success){
        NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
    }
    return success;
}

+ (NSString*)absolutePath:(NSString*)relativePath inStorage:(NSString*)storage {
    NSURL *baseDir = [SystemFileManager baseDirForStorage:storage];
    return [[baseDir URLByAppendingPathComponent:relativePath] path];
}

// Extra method for integration from other modules / native code
+ (NSString*)moveFileFromUrl:(NSURL*)location toRelativePath:(NSString*)relativePath inStorage:(NSString*)storage {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *baseDir = [SystemFileManager baseDirForStorage:storage];
    NSURL *fullPath = [baseDir URLByAppendingPathComponent:relativePath];
    [SystemFileManager createDirectoriesIfNeeded:fullPath];
    [fileManager moveItemAtURL:location toURL:fullPath error:nil];
    if ([storage isEqual:STORAGE_IMPORTANT]) {
        [SystemFileManager addSkipBackupAttributeToItemAtPath:[fullPath path]];
    }
    return [fullPath path];
}

@end
